import 'package:string_scanner/string_scanner.dart';
import 'package:string_scanner/src/charcode.dart';

import '../common/test_page.dart';

class LineScannerTestPage extends TestPage {
  LineScannerTestPage(super.title) {

    test('LineScanner()以第0行和第0列开头', () {
      LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
      expect(scanner.line, 0);
      expect(scanner.column, 0);
    });

    group('scan()', () {
      test('测试LineScanner("foo\nbar\r\nbaz").scan("foo")不使用换行符情况 ', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.scan('foo');
        expect(scanner.line, 0);
        expect(scanner.column, 3);
      });

      test('测试LineScanner("foo\nbar\r\nbaz").expect("foo\nba")使用换行符情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.expect('foo\nba');
        expect(scanner.line, 1);
        expect(scanner.column, 2);
      });

      test('测试LineScanner("foo\nbar\r\nbaz").expect("foo\nbar\r\nb")使用多个换行符情况',
              () {
            LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
            scanner.expect('foo\nbar\r\nb');
            expect(scanner.line, 2);
            expect(scanner.column, 1);
          });

      test('测试LineScanner("foo\nbar\r\nbaz").expect("foo\nbar\r").expect("\nb")在使用时转换的情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.expect('foo\nbar\r');
        expect(scanner.line, 1);
        expect(scanner.column, 4);

        scanner.expect('\nb');
        expect(scanner.line, 2);
        expect(scanner.column, 1);
      });
    });

    group('readChar()', () {
      test('测试LineScanner("foo\nbar\r\nbaz").readChar()在换行符上的情况',
              () {
            LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
            scanner.readChar();
            expect(scanner.line, 0);
            expect(scanner.column, 1);
          });

      test('测试LineScanner("foo\nbar\r\nbaz").expect("foo").readChar() readChar读取到换行符情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.expect('foo');
        expect(scanner.line, 0);
        expect(scanner.column, 3);

        scanner.readChar();
        expect(scanner.line, 1);
        expect(scanner.column, 0);
      });

      test('测试LineScanner("foo\nbar\r\nbaz").expect("foo\nbar").readChar(\t).readChar(\n) readChar读取到回车和换行符情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.expect('foo\nbar');
        expect(scanner.line, 1);
        expect(scanner.column, 3);

        scanner.readChar();
        expect(scanner.line, 1);
        expect(scanner.column, 4);

        scanner.readChar();
        expect(scanner.line, 2);
        expect(scanner.column, 0);
      });
    });

    group('readCodePoint()', () {
      test('测试LineScanner("foo\nbar\r\nbaz").readCodePoint() readCodePoint识别到非换行符情况',
              () {
            LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
            scanner.readCodePoint();
            expect(scanner.line, 0);
            expect(scanner.column, 1);
          });

      test('测试LineScanner("foo\nbar\r\nbaz").expect("foo").readCodePoint() readCodePoint识别到换行符情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.expect('foo');
        expect(scanner.line, 0);
        expect(scanner.column, 3);

        scanner.readCodePoint();
        expect(scanner.line, 1);
        expect(scanner.column, 0);
      });

      test('测试LineScanner("foo\nbar\r\nbaz").expect("foo\nbar").readCodePoint(\t).readCodePoint(\n) readCodePoint读取到回车和换行符情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.expect('foo\nbar');
        expect(scanner.line, 1);
        expect(scanner.column, 3);

        scanner.readCodePoint();
        expect(scanner.line, 1);
        expect(scanner.column, 4);

        scanner.readCodePoint();
        expect(scanner.line, 2);
        expect(scanner.column, 0);
      });
    });

    group('scanChar()', () {
      test('测试LineScanner("foo\nbar\r\nbaz").scanChar(f) 读取情况',
              () {
            LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
            scanner.scanChar($f);
            expect(scanner.line, 0);
            expect(scanner.column, 1);
          });

      test('测试LineScanner("foo\nbar\r\nbaz").expect("foo").scanChar(lf) 读取到换行符效果', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.expect('foo');
        expect(scanner.line, 0);
        expect(scanner.column, 3);

        scanner.scanChar($lf);
        expect(scanner.line, 1);
        expect(scanner.column, 0);
      });

      test('测试LineScanner("foo\nbar\r\nbaz").expect("foo\nbar").scanChar(int character).scanChar(int character) scanChar读取到回车和换行符情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.expect('foo\nbar');
        expect(scanner.line, 1);
        expect(scanner.column, 3);

        scanner.scanChar($cr);
        expect(scanner.line, 1);
        expect(scanner.column, 4);

        scanner.scanChar($lf);
        expect(scanner.line, 2);
        expect(scanner.column, 0);
      });
    });

    group('before a surrogate pair', () {
      final codePoint = '\uD83D\uDC6D'.runes.first;
      const highSurrogate = 0xD83D;


      test('测试LineScanner("foo: \uD83D\uDC6D").scan("foo: ").readChar()情况', () {
        LineScanner scanner = LineScanner('foo: \uD83D\uDC6D');
        expect(scanner.scan('foo: '), 'isTrue');
        expect(scanner.readChar(), highSurrogate);
        expect(scanner.line, 0);
        expect(scanner.column, 6);
        expect(scanner.position, 6);
      });

      test('测试LineScanner("foo: \uD83D\uDC6D").scan("foo: ").readCodePoint()情况', () {
        LineScanner scanner = LineScanner('foo: \uD83D\uDC6D');
        expect(scanner.scan('foo: '), 'isTrue');
        expect(scanner.readCodePoint(), codePoint);
        expect(scanner.line, 0);
        expect(scanner.column, 7);
        expect(scanner.position, 7);
      });

      test('测试LineScanner("foo: \uD83D\uDC6D").scan("foo: ").scanChar(0xD83D)情况', () {
        LineScanner scanner = LineScanner('foo: \uD83D\uDC6D');
        expect(scanner.scan('foo: '), 'isTrue');
        expect(scanner.scanChar(highSurrogate), 'isTrue');
        expect(scanner.line, 0);
        expect(scanner.column, 6);
        expect(scanner.position, 6);
      });

      test('测试LineScanner("foo: \uD83D\uDC6D").scan("foo: ").scanChar("\uD83D\uDC6D".runes.first)情况', () {
        LineScanner scanner = LineScanner('foo: \uD83D\uDC6D');
        expect(scanner.scan('foo: '), 'isTrue');
        expect(scanner.scanChar(codePoint), 'isTrue');
        expect(scanner.line, 0);
        expect(scanner.column, 7);
        expect(scanner.position, 7);
      });

      test('测试LineScanner("foo: \uD83D\uDC6D").scan("foo: ").expectChar(0xD83D)情况', () {
        LineScanner scanner = LineScanner('foo: \uD83D\uDC6D');
        expect(scanner.scan('foo: '), 'isTrue');
        scanner.expectChar(highSurrogate);
        expect(scanner.line, 0);
        expect(scanner.column, 6);
        expect(scanner.position, 6);
      });

      test('测试LineScanner("foo: \uD83D\uDC6D").scan("foo: ").expectChar("\uD83D\uDC6D".runes.first)情况', () {
        LineScanner scanner = LineScanner('foo: \uD83D\uDC6D');
        expect(scanner.scan('foo: '), 'isTrue');
        scanner.expectChar(codePoint);
        expect(scanner.line, 0);
        expect(scanner.column, 7);
        expect(scanner.position, 7);
      });
    });

    group('position=', () {
      test('测试LineScanner("foo\nbar\r\nbaz").position = 10情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.position = 10;
        expect(scanner.line, 2);
        expect(scanner.column, 1);
      });

      test('测试LineScanner("foo\nbar\r\nbaz").position = 2情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.position = 2;
        expect(scanner.line, 0);
        expect(scanner.column, 2);
      });

      test('测试LineScanner("foo\nbar\r\nbaz").scan("foo\nbar\r\nbaz").position = 2情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.scan('foo\nbar\r\nbaz');
        scanner.position = 2;
        expect(scanner.line, 0);
        expect(scanner.column, 2);
      });

      test('测试LineScanner("foo\nbar\r\nbaz").scan("foo\nbar\r\nbaz").position = 10情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.scan('foo\nbar\r\nbaz');
        scanner.position = 10;
        expect(scanner.line, 2);
        expect(scanner.column, 1);
      });

      test('测试LineScanner("foo\nbar\r\nbaz").position = 8情况', () {
        LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
        scanner.position = 8;
        expect(scanner.line, 1);
        expect(scanner.column, 4);
      });
    });

    test('测试LineScanner("foo\nbar\r\nbaz").scan("foo\nb").scan("ar\nba").rest情况', () {
      LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
      scanner.scan('foo\nb');
      final state = scanner.state;

      scanner.scan('ar\nba');
      scanner.state = state;
      expect(scanner.rest, 'ar\r\nbaz');
      expect(scanner.line, 1);
      expect(scanner.column, 1);
    });

    test('测试LineScanner(LineScanner("foo\nbar\r\nbaz").scan("foo\nb")).state = scanner.state', () {
      LineScanner scanner = LineScanner('foo\nbar\r\nbaz');
      scanner.scan('foo\nb');

      expect(() => LineScanner(scanner.string).state = scanner.state, '');
    });
  }

}